package com.activiti.z_six.service.impl;

import com.activiti.z_six.entity.process.FlowEntity;
import com.activiti.z_six.entity.process.FlowSort;
import com.activiti.z_six.entity.process.ProcessEntity;

import com.activiti.z_six.entity.taskAssignee.FlowElementAttrs;
import com.activiti.z_six.entity.process.FlowEnum;
import com.activiti.z_six.entity.taskAssignee.OvProcessInstance;
import com.activiti.z_six.mapper.processMapper.FlowEntityMapper;
import com.activiti.z_six.mapper.processMapper.FlowSortMapper;
import com.activiti.z_six.mapper.processMapper.ProcessEntityMapper;
import com.activiti.z_six.mapper.taskAssigneeMapper.FlowElementAttrsMapper;
import com.activiti.z_six.mapper.taskAssigneeMapper.OvProcessInstanceMapper;
import com.activiti.z_six.security.RedisUtils;
import com.activiti.z_six.service.AssigneeUserService;
import com.activiti.z_six.service.ProcessDefinitionService;
import com.activiti.z_six.util.AjaxResponse;
import com.activiti.z_six.util.SystemConfig;

import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
    @Autowired //流程部署服务
    private RepositoryService repositoryService;
    @Autowired
    private OvProcessInstanceMapper ovProcessInstanceMapper;
    @Autowired //流程分类服务
    private FlowSortMapper flowSortMapper;
    @Autowired //流程定义自定义服务
    private FlowEntityMapper flowEntityMapper;
    @Autowired //流程实例自定义服务
    private ProcessEntityMapper processEntityMapper;
    @Autowired //redis服务
    private RedisUtils redisUtils;
    @Autowired //设置处理人服务
    private AssigneeUserService assigneeUserService;
    @Autowired
    private FlowElementAttrsMapper flowElementAttrsMapper;

    /*
    获取流程部署列表
     */
    @Override
    public AjaxResponse getDeployment(Integer page,Integer pagesize,String sortid,String name){
        try{
            int startIndex=(page-1)*pagesize;
            int maxIndex=startIndex+pagesize;

            //流程定义总数量
            List<ProcessDefinition> processDefinitionlist = repositoryService.createProcessDefinitionQuery()
                    .latestVersion()
                    .list();

            List<HashMap<String, Object>> listMap= new ArrayList<HashMap<String, Object>>();
            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
                    .latestVersion()
                    .listPage(startIndex,maxIndex);

            list.sort((y,x)->x.getVersion()-y.getVersion());

            for (ProcessDefinition pd : list) {
                if(!SystemConfig.IsNullOrEmpty(sortid))
                {
                    if(!sortid.equals(pd.getEngineVersion()))
                        continue;
                }
                if(!SystemConfig.IsNullOrEmpty(name))
                {
                    if(!name.contains(pd.getName()))
                        continue;
                }
                HashMap<String, Object> hashMap = new HashMap<>();
                //流程定义id
                hashMap.put("procId", pd.getId());
                //流程定义名称
                hashMap.put("name", pd.getName());
                //流程key
                hashMap.put("procKey", pd.getKey());
                //resourceName
                hashMap.put("resourceName", pd.getResourceName());
                //流程部署ID
                hashMap.put("deploymentID", pd.getDeploymentId());
                hashMap.put("flowSort",pd.getEngineVersion());
                //版本
                hashMap.put("version", pd.getVersion());
                listMap.add(hashMap);
            }
            HashMap<String ,Object> hashMap=new HashMap<>();
            hashMap.put("list",listMap);
            hashMap.put("total",processDefinitionlist.size());
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), hashMap);
        }
        catch (Exception ex){
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "查询失败", ex.toString());
        }
    }
    /*
    发布流程
     */
    @Override
    public AjaxResponse deployWithBPMNJS(String BPMNXml){
        try {
            Deployment deployment = repositoryService.createDeployment()
                    .addString("createWithBPMNJS.bpmn",BPMNXml)
                    .deploy();

            OvProcessInstance ovProcessInstance=ovProcessInstanceMapper.getProcessInsByDeployId(deployment.getId());
            BpmnModel bpmnModel = repositoryService.getBpmnModel(ovProcessInstance.getId_());
            //获取流程信息
            Process process=bpmnModel.getProcesses().get(0);
            Collection<FlowElement> flowElements=process.getFlowElements();
            for(FlowElement flowElement : flowElements){
                if (flowElement instanceof UserTask){
                    UserTask userTask=(UserTask) flowElement;
                    String usertaskId=userTask.getId();
                    String assigneeString ="";
                    //读取缓存中设置的处理人数据
                    if(redisUtils.exists(usertaskId)){
                        assigneeString=redisUtils.get(usertaskId).toString();
                        assigneeUserService.deleteAssigneeUserByTaskid(usertaskId);
                        assigneeUserService.setAssigneeUser(assigneeString,usertaskId);
                    }
                    Boolean isExists=true;
                    FlowElementAttrs flowElementAttrs=flowElementAttrsMapper.getFlowElementAttrs(usertaskId);
                    if(flowElementAttrs==null){
                        flowElementAttrs=new FlowElementAttrs();
                        flowElementAttrs.setId(UUID.randomUUID().toString());
                        flowElementAttrs.setTask_def_key(usertaskId);
                        isExists=false;
                    }
                    if(redisUtils.exists(usertaskId+"_returnWay")){
                        flowElementAttrs.setReturnWay(redisUtils.get(usertaskId+"_returnWay").toString());
                    }
                    else{
                        flowElementAttrs.setReturnWay("none");
                    }
                    if(redisUtils.exists(usertaskId+"_jumpWay")){
                        flowElementAttrs.setJumpWay(redisUtils.get(usertaskId+"_jumpWay").toString());
                    }
                    else{
                        flowElementAttrs.setJumpWay("none");
                    }
                    if(redisUtils.exists(usertaskId+"_runWay")){
                        flowElementAttrs.setRunWay(redisUtils.get(usertaskId+"_runWay").toString());
                    }
                    else{
                        flowElementAttrs.setRunWay("none");
                    }
                    if(redisUtils.exists(usertaskId+"_ccWay")){
                        flowElementAttrs.setCcWay(redisUtils.get(usertaskId+"_ccWay").toString());
                    }
                    else{
                        flowElementAttrs.setCcWay("none");
                    }
                    if(redisUtils.exists(usertaskId+"_autoCCWay")){
                        flowElementAttrs.setAutoCCWay(redisUtils.get(usertaskId+"_autoCCWay").toString());
                    }
                    else{
                        flowElementAttrs.setAutoCCWay("none");
                    }
                    if(redisUtils.exists(usertaskId+"_transfer")){
                        flowElementAttrs.setTransfer(Integer.parseInt(redisUtils.get(usertaskId+"_transfer").toString()));
                    }
                    else{
                        flowElementAttrs.setTransfer(0);
                    }
                    if(redisUtils.exists(usertaskId+"_countersign")){
                        flowElementAttrs.setCountersign(Integer.parseInt(redisUtils.get(usertaskId+"_countersign").toString()));
                    }
                    else{
                        flowElementAttrs.setCountersign(0);
                    }
                    if(redisUtils.exists(usertaskId+"_endTask")){
                        flowElementAttrs.setEndTask(Integer.parseInt(redisUtils.get(usertaskId+"_endTask").toString()));
                    }
                    else{
                        flowElementAttrs.setEndTask(0);
                    }
                    if(redisUtils.exists(usertaskId+"_refuse")){
                        flowElementAttrs.setRefuse(Integer.parseInt(redisUtils.get(usertaskId+"_refuse").toString()));
                    }
                    else{
                        flowElementAttrs.setRefuse(0);
                    }

                    flowElementAttrs.setProcess_key(ovProcessInstance.getKey_());

                    if(isExists){
                        flowElementAttrsMapper.updateFlowElementAttrs(flowElementAttrs);
                    }else {
                        flowElementAttrsMapper.setFlowElementAttrs(flowElementAttrs);
                    }
                }
            }

            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), deployment.getId());
        } catch (Exception e) {
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "部署流程失败", e.toString());
        }
    }
    /*
    更新业务配置
     */
    @Override
    public AjaxResponse updateDeployment(String process_key,String deploymentId,String flowSort,String name,
                                         String form_type,String formMap,String form_url,String mapJson){
        try{
            //更新流程部署信息，将引擎版本号作为流程类别
            FlowEntity flowEntity=new FlowEntity();
            flowEntity.setId_(deploymentId);
            flowEntity.setProcessKey(process_key);
            flowEntity.setEngine_version_(flowSort);
            flowEntity.setName_(name);
            flowEntityMapper.updateFlowEntity(flowEntity);
//
//            //更新流程定义信息，将引擎版本号作为流程类别
//            ProcessEntity processEntity=new ProcessEntity();
//            processEntity.setDeployment_id_(deploymentId);
//            processEntity.setEngine_version_(flowSort);
//            processEntity.setName_(name);
//            processEntityMapper.updateProcessEntity(processEntity);

            OvProcessInstance ovProcessInstance=ovProcessInstanceMapper.getProcessInsByDeployId(deploymentId);
            FlowElementAttrs flowElementAttrs=new FlowElementAttrs();
            flowElementAttrs.setProcess_key(ovProcessInstance.getKey_());
            flowElementAttrs.setForm_type(form_type);
            flowElementAttrs.setFormMap(formMap);
            flowElementAttrs.setForm_url(form_url);
            //flowElementAttrs.setMapJson(mapJson);
            flowElementAttrsMapper.updateFlowMap(flowElementAttrs);

            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), "执行成功。");
        }
        catch (Exception ex){
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "更新业务配置失败", ex.toString());
        }
    }
    @Override
    public FlowElementAttrs getFlowElementAttrs(String task_def_id){
        FlowElementAttrs flowElementAttrs=flowElementAttrsMapper.getFlowElementAttrs(task_def_id);
        return flowElementAttrs;
    }
    @Override
    public FlowElementAttrs getFlowElementFormAttrs(String process_key){
        FlowElementAttrs flowElementAttrs=flowElementAttrsMapper.getFlowElementFormAttrs(process_key);
        return flowElementAttrs;
    }
    @Override
    public HashMap<String,Object> getFlowEnum(){
        List<FlowEnum> flowEnums=flowElementAttrsMapper.enumList();
        HashMap<String,Object> hashMap=new HashMap<>();

        List<HashMap<String,Object>> taskRuleList=new ArrayList<>();

        List<HashMap<String,Object>> returnWayList=new ArrayList<>();

        List<HashMap<String,Object>> jumpWayList=new ArrayList<>();

        List<HashMap<String,Object>> ccWayList=new ArrayList<>();

        List<HashMap<String,Object>> autoCCWayList=new ArrayList<>();

        List<HashMap<String,Object>> sexSelectList=new ArrayList<>();

        List<HashMap<String,Object>> userSatetList=new ArrayList<>();

        List<HashMap<String,Object>> startRulesList=new ArrayList<>();


        for(FlowEnum fe:flowEnums){
            if(fe.getRules().equals("taskRules")){
                HashMap<String,Object> taskRules=new HashMap<>();
                taskRules.put("ruleKey",fe.getKey());
                taskRules.put("taskRuleName",fe.getName());
                taskRuleList.add(taskRules);
            }
            else if(fe.getRules().equals("returnWay")){
                HashMap<String,Object> returnWay=new HashMap<>();
                returnWay.put("returnWayKey",fe.getKey());
                returnWay.put("returnWayName",fe.getName());
                returnWayList.add(returnWay);
            }
            else if(fe.getRules().equals("jumpWay")){
                HashMap<String,Object> jumpWay=new HashMap<>();
                jumpWay.put("jumpWayKey",fe.getKey());
                jumpWay.put("jumpWayName",fe.getName());
                jumpWayList.add(jumpWay);
            }
            else if(fe.getRules().equals("ccWay")){
                HashMap<String,Object> ccWay=new HashMap<>();
                ccWay.put("ccKey",fe.getKey());
                ccWay.put("ccName",fe.getName());
                ccWayList.add(ccWay);
            }
            else if(fe.getRules().equals("autoCCWay")){
                HashMap<String,Object> autoCCWay=new HashMap<>();
                autoCCWay.put("autoCCKey",fe.getKey());
                autoCCWay.put("autoCCName",fe.getName());
                autoCCWayList.add(autoCCWay);
            }
            else if(fe.getRules().equals("sexSelect")){
                HashMap<String,Object> sexSelect=new HashMap<>();
                sexSelect.put("value",fe.getKey());
                sexSelect.put("label",fe.getName());
                sexSelectList.add(sexSelect);
            }
            else if(fe.getRules().equals("userSatet")){
                HashMap<String,Object> userSatet=new HashMap<>();
                userSatet.put("value",fe.getKey());
                userSatet.put("label",fe.getName());
                userSatetList.add(userSatet);
            }
            else if(fe.getRules().equals("startRules")){
                HashMap<String,Object> startRules=new HashMap<>();
                startRules.put("ruleKey",fe.getKey());
                startRules.put("taskRuleName",fe.getName());
                startRulesList.add(startRules);
            }
        }
        hashMap.put("taskRules",taskRuleList);
        hashMap.put("returnWay",returnWayList);
        hashMap.put("jumpWay",jumpWayList);
        hashMap.put("ccWay",ccWayList);
        hashMap.put("autoCCWay",autoCCWayList);
        hashMap.put("sexSelect",sexSelectList);
        hashMap.put("userSatet",userSatetList);
        hashMap.put("startRules",startRulesList);
        return hashMap;
    }
    /*
    获取流程分类分页
     */
    @Override
    public AjaxResponse getFlowSort(Integer page,Integer pagesize){
        try{
            List<FlowSort> flowSortList= flowSortMapper.getFlowSort(page,pagesize);
            List<HashMap<String, Object>> listMap= new ArrayList<HashMap<String, Object>>();
            for (FlowSort fs : flowSortList) {
                HashMap<String, Object> hashMap = new HashMap<>();
                //流程定义id
                hashMap.put("Id", fs.getId());
                //流程定义名称
                hashMap.put("name", fs.getName());
                hashMap.put("parentid", fs.getParentId());
                listMap.add(hashMap);
            }

            HashMap<String ,Object> hashMap=new HashMap<>();
            hashMap.put("list",listMap);
            hashMap.put("total",flowSortMapper.getFlowSortTotal());

            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), hashMap);
        }
        catch (Exception ex){
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "查询失败", ex.toString());
        }
    }
    /*
    获取全部流程分类
     */
    @Override
    public AjaxResponse getFlowSortAll(){
        try{
            List<FlowSort> flowSortList= flowSortMapper.getFlowSortAll();
            List<HashMap<String, Object>> listMap= new ArrayList<HashMap<String, Object>>();
            for (FlowSort fs : flowSortList) {
                HashMap<String, Object> hashMap = new HashMap<>();
                //流程定义id
                hashMap.put("Id", fs.getId());
                //流程定义名称
                hashMap.put("name", fs.getName());
                hashMap.put("parentid", fs.getParentId());
                listMap.add(hashMap);
            }

            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), listMap);
        }
        catch (Exception ex){
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "查询失败", ex.toString());
        }
    }
    /*
    获取全部流程分类树
     */
    @Override
    public AjaxResponse getFlowSortTree(){
        try{
            List<FlowSort> flowSortList= flowSortMapper.getFlowSortAll();
            //2、组装树形结构
            List<FlowSort> newList = flowSortList.stream()
                    .filter(t -> t.getParentId() == 0)
                    .map((menu) -> {
                        menu.setChildren(this.getChildren(menu,flowSortList));
                        return menu;
                    })
                    .collect(Collectors.toList());

            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), newList);
        }
        catch (Exception ex){
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "查询失败", ex.toString());
        }
    }
    @Override
    public AjaxResponse getSatrtPageData(){
        try{
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String username = authentication.getName();

            HashMap map=new HashMap<>();
            List<HashMap<String,Object>> mapList=new ArrayList<>();
            List<FlowSort> flowSortList= flowSortMapper.getFlowSortAll();
            List<FlowEntity> commProceList=flowEntityMapper.getCommProceList(username);
            for(FlowSort fs:flowSortList){
                HashMap<String,Object> hashMap=new HashMap<>();
                hashMap.put("id",fs.getId());
                hashMap.put("name",fs.getName());

                List<FlowEntity> flowEntities=flowEntityMapper.getFlowListBySort(fs.getId().toString());

                if(flowEntities.size()>0){
                    hashMap.put("flowList",flowEntities);
                }
                else{
                    hashMap.put("flowList",new ArrayList<>());
                }
                mapList.add(hashMap);
            }
            map.put("commProceList",commProceList);
            map.put("flowList",mapList);

            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), map);
        }
        catch (Exception ex){
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "查询失败", ex.toString());
        }
    }
    /**
     * 递归查找当前菜单的子菜单
     * @param root 单个对象
     * @param all 所有的集合
     * @return 排序后的子类
     */
    private List<FlowSort> getChildren(FlowSort root,List<FlowSort> all){
        List<FlowSort> childrenList = all.stream()
                .filter(t -> t.getParentId() == root.getId())
                .map(g -> {
                    //找子菜单
                    g.setChildren(getChildren(g,all));
                    return g;
                })
                //菜单排序
                .collect(Collectors.toList());

        return childrenList;
    }
    /*
    新增流程类别
     */
    @Override
    public AjaxResponse addFlowSort(String name,Long parentId){
        try{
            FlowSort flowSort=new FlowSort();
            flowSort.setName(name);
            flowSort.setParentId(parentId);
            int i=flowSortMapper.addFlowSort(flowSort);

            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), "执行成功。");
        }catch (Exception ex){
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "创建失败", ex.toString());
        }
    }
    /*
    流程类别保存修改
     */
    @Override
    public AjaxResponse saveFlowSort(Long id,String name,Long parentId){
        try{
            FlowSort flowSort=new FlowSort();
            flowSort.setId(id);
            flowSort.setName(name);
            flowSort.setParentId(parentId);
            int i=flowSortMapper.saveFlowSort(flowSort);

            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), "执行成功。");
        }
        catch (Exception ex){
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "修改失败", ex.toString());
        }
    }

    /**
     * 删除流程定义
     * @param deploymentId
     * @return
     */
    @Override
    public AjaxResponse deleteDefinition(String deploymentId){
        try {
            repositoryService.deleteDeployment(deploymentId, true);
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), "执行成功。");
        }
        catch (Exception ex){
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "删除失败", ex.toString());
        }
    }
    /**
     * 删除流程分类
     * @param id
     * @param name
     * @param parentId
     * @return
     */
    @Override
    public AjaxResponse deleteFlowSort(Long id,String name,Long parentId){
        try{
            FlowSort flowSort=new FlowSort();
            flowSort.setId(id);
            flowSort.setName(name);
            flowSort.setParentId(parentId);
            int i=flowSortMapper.deleteFlowSort(flowSort);

            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.SUCCESS.getCode(),
                    SystemConfig.ResponseCode.SUCCESS.getDesc(), "执行成功。");
        }
        catch (Exception ex){
            return AjaxResponse.AjaxData(SystemConfig.ResponseCode.ERROR.getCode(),
                    "删除失败", ex.toString());
        }
    }
}
